/*
 * Copyright (c) 2006-2019, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2017-07-24     Tanek        the first version
 * 2018-11-12     Ernest Chen  modify copyright
 */
#include "definitions.h"

#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <rthw.h>
#include <rtthread.h>

#include "rtdevice.h"

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
#define RT_HEAP_SIZE 4096
static uint32_t rt_heap[RT_HEAP_SIZE];     // heap default size: 4K(1024 * 4)
RT_WEAK void *rt_heap_begin_get (void)
{
    return rt_heap;
}

RT_WEAK void *rt_heap_end_get (void)
{
    return rt_heap + RT_HEAP_SIZE;
}
#endif

#ifdef RT_USING_CONSOLE
void rt_hw_console_output (const char *str)
{
    rt_size_t i = 0, size = 0;
    static char a = '\r';

    size = rt_strlen (str);

    if (SERCOM3_USART_WriteFreeBufferCountGet() < size)
        rt_thread_delay (10);

    rt_enter_critical();
    for (i = 0; i < size; i++) {
        if (* (str + i) == '\n') {
            SERCOM3_USART_Write ((uint8_t *)&a, 1);
        }
        SERCOM3_USART_Write ((uint8_t *) (str + i), 1);
    }
    rt_exit_critical();
}

int rt_hw_console_getchar (void)
{
    int rev_char = 0x00;

    if (SERCOM3_USART_Read ((void *)&rev_char, 1) > 0)
        return rev_char;

    rt_thread_delay (10);
    return (int)-1;
}
#endif

/**
 * This function will initial your board.
 */
void rt_hw_board_init()
{
    /* Initialize all modules */
    SYS_Initialize ( NULL );

    /* System Tick Configuration */
    SysTick_Config (48000000UL / RT_TICK_PER_SECOND);

#if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP)
    rt_system_heap_init (rt_heap_begin_get(), rt_heap_end_get());
#endif

    /* Pin driver initialization is open by default */
#ifdef RT_USING_PIN
    extern int rt_hw_pin_init (void);
    rt_hw_pin_init();
#endif

    /* Call components board initial (use INIT_BOARD_EXPORT()) */
#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif

#if defined(RT_USING_CONSOLE) && defined(RT_USING_SERIAL)
    //rt_console_set_device (RT_CONSOLE_DEVICE_NAME);
#endif
}

void SysTick_Handler (void)
{
    /* enter interrupt */
    rt_interrupt_enter();

    rt_tick_increase();

    /* leave interrupt */
    rt_interrupt_leave();
}
